package maps
{
	import flash.geom.Point;
	
	public class Map
	{
		private var _map:Array;
		private var _width:int;
		private var _height:int;
		
		public function Map(width:int, height:int)
		{
			_width = width;
			_height = height;
			
			_map = new Array(width * height);
		}
		
		/**
		 *
		 * 获得与此节点相邻且种类相同的节点的数组
		 *  
		 * @param tile
		 * @return 
		 * 
		 */		
		public function getSameType(tile:Tile, closeTile:Vector.<Tile> = null):Vector.<Tile>
		{
			var tileV:Vector.<Tile> = new Vector.<Tile>();
			if(closeTile == null){
				closeTile = new Vector.<Tile>();
			}
			tileV.push(tile);
			closeTile.push(tile);
			var neighbours:Vector.<Tile> = getNeighbours(tile);
			for(var i:int = 0; i < neighbours.length; i++){
				var neighbour:Tile = neighbours[i];
				//此邻居不在关闭列表并且种类相同
				if(closeTile.indexOf(neighbour) < 0 && neighbour.type == tile.type)
				{
					if(neighbour.type == tile.type){
						tileV = tileV.concat(getSameType(neighbour, closeTile));
					}else{
						closeTile.push(neighbour);
					}
				}
			}
			return tileV;
		}
		
		/**
		 *
		 * 获得此列第一个空的节点在的行数
		 *  
		 * @param col
		 * @return 
		 * 
		 */		
		public function getColEmptyIndex(col:int):int
		{
			if(col >= _height){
				return -1;
			}
			for(var i:int = 0; i < _height; i++)
			{
				if(getTileAt(new Point(col, i)).type == -1){
					return i;
				}
			}
			return _height;
		}
		
		/**
		 *
		 * 设置节点
		 *  
		 * @param tile
		 * 
		 */		
		public function setTile(tile:Tile):void
		{
			var p:Point = tile.getPosition();
			if(isValidPosition(p)){
				_map[calIndex(p)] = tile;
			}
			
		}
		
		/**
		 *
		 * 获得于此节点相邻的节点数组
		 *  
		 * @param tile
		 * @return 
		 * 
		 */		
		public function getNeighbours(tile:Tile) : Vector.<Tile>
		{
			var position:Point = (tile as Tile).getPosition();
			
			var x:Number = position.x;
			var y:Number = position.y;
			
			var neighbours:Vector.<Tile> = new Vector.<Tile>();
			if(this.isValidPosition(new Point(x-1, y))) neighbours.push(this.getTileAt(new Point(x-1, y)));
			if(this.isValidPosition(new Point(x, y-1))) neighbours.push(this.getTileAt(new Point(x, y-1)));
			if(this.isValidPosition(new Point(x, y+1))) neighbours.push(this.getTileAt(new Point(x, y+1)));
			if(this.isValidPosition(new Point(x+1, y))) neighbours.push(this.getTileAt(new Point(x+1, y)));
			
			return neighbours;
		}
		
		/**
		 *
		 * 获得节点
		 *  
		 * @param position
		 * @return 
		 * 
		 */		
		public function getTileAt(position:Point):Tile
		{
			if(isValidPosition(position))
			{
				return _map[calIndex(position)];
			}
			return null;
		}
		
		/**
		 *
		 * 返回地图的尺寸
		 *  
		 * @return 
		 * 
		 */		
		private function getSize():Point
		{
			return new Point(_width, _height);
		}
		
		/**
		 *
		 * 计算此节点在数组中的键值
		 *  
		 * @param p
		 * @return 
		 * 
		 */		
		private function calIndex(p:Point):int
		{
			return p.x * _width + p.y;
		}
		
		/**
		 *
		 * 此点在地图上是否存在
		 *  
		 * @param position
		 * @return 
		 * 
		 */		
		private function isValidPosition(position:Point):Boolean
		{
			if(_map == null) return false;
			if(position.x < 0 || position.y < 0) return false;
			
			var size:Point = getSize();
			
			return position.x < size.x && position.y < size.y;
		}
	}
}